package com.wzb.mybatisplus.bitaction;

import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.math.ec.ECPoint;

import java.math.BigInteger;
import java.security.Security;

public class BitcoinWIFConverter {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * 专门生成34个字符Base58格式的压缩公钥
     */
    public static String wifTo34CharPublicKey(String wifPrivateKey) {
        try {
            // 1. 从WIF私钥提取原始私钥
            byte[] privateKeyBytes = extractPrivateKeyFromWIF(wifPrivateKey);

            // 2. 使用私钥生成压缩公钥
            byte[] compressedPublicKey = generateCompressedPublicKey(privateKeyBytes);

            // 3. 转换为Base58格式（通常是34个字符）
            String publicKeyBase58 = base58Encode(compressedPublicKey);

            return publicKeyBase58;

        } catch (Exception e) {
            throw new IllegalArgumentException("转换失败: " + e.getMessage());
        }
    }

    /**
     * 从WIF私钥提取原始私钥字节
     */
    private static byte[] extractPrivateKeyFromWIF(String wifPrivateKey) {
        // Base58解码
        byte[] decoded = base58Decode(wifPrivateKey);

        if (decoded.length < 33) {
            throw new IllegalArgumentException("无效的WIF格式");
        }

        // 验证网络字节（0x80为主网）
        if (decoded[0] != (byte) 0x80) {
            throw new IllegalArgumentException("不是主网WIF私钥");
        }

        // 提取私钥（32字节）
        byte[] privateKeyBytes = new byte[32];
        System.arraycopy(decoded, 1, privateKeyBytes, 0, 32);

        return privateKeyBytes;
    }

    /**
     * 生成压缩公钥
     */
    private static byte[] generateCompressedPublicKey(byte[] privateKeyBytes) {
        try {
            ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");

            // 私钥转换为BigInteger
            BigInteger privateKey = new BigInteger(1, privateKeyBytes);

            // 计算公钥点：公钥 = 私钥 * G
            ECPoint publicKeyPoint = spec.getG().multiply(privateKey);

            // 获取压缩格式的公钥（33字节）
            return publicKeyPoint.getEncoded(true);

        } catch (Exception e) {
            throw new RuntimeException("生成公钥失败: " + e.getMessage());
        }
    }

    /**
     * Base58解码
     */
    private static byte[] base58Decode(String input) {
        final String ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
        final BigInteger BASE = BigInteger.valueOf(58);

        BigInteger num = BigInteger.ZERO;

        // 计算前导1的数量
        int leadingOnes = 0;
        for (int i = 0; i < input.length() && input.charAt(i) == '1'; i++) {
            leadingOnes++;
        }

        // 转换为BigInteger
        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            int digit = ALPHABET.indexOf(c);
            if (digit == -1) {
                throw new IllegalArgumentException("无效的Base58字符: " + c);
            }
            num = num.multiply(BASE).add(BigInteger.valueOf(digit));
        }

        // 转换为字节数组
        byte[] bytes = num.toByteArray();

        // 处理符号位和前导零
        if (bytes.length > 0 && bytes[0] == 0) {
            byte[] temp = new byte[bytes.length - 1 + leadingOnes];
            System.arraycopy(bytes, 1, temp, leadingOnes, bytes.length - 1);
            return temp;
        } else {
            byte[] temp = new byte[bytes.length + leadingOnes];
            System.arraycopy(bytes, 0, temp, leadingOnes, bytes.length);
            return temp;
        }
    }

    /**
     * Base58编码（优化版本，确保输出长度）
     */
    private static String base58Encode(byte[] input) {
        final String ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
        final BigInteger BASE = BigInteger.valueOf(58);

        BigInteger num = new BigInteger(1, input);
        StringBuilder sb = new StringBuilder();

        // 计算前导零
        int leadingZeros = 0;
        for (byte b : input) {
            if (b == 0) leadingZeros++;
            else break;
        }

        // Base58编码
        while (num.compareTo(BigInteger.ZERO) > 0) {
            BigInteger[] divmod = num.divideAndRemainder(BASE);
            num = divmod[0];
            int digit = divmod[1].intValue();
            sb.insert(0, ALPHABET.charAt(digit));
        }

        // 添加前导'1'
        for (int i = 0; i < leadingZeros; i++) {
            sb.insert(0, '1');
        }

        return sb.toString();
    }

    /**
     * 验证生成的公钥是否为34个字符
     */
    public static boolean is34CharPublicKey(String publicKey) {
        return publicKey != null && publicKey.length() == 34;
    }

    /**
     * 批量转换工具
     */
    public static class BatchConverter {
        public static ConversionResult convertMultiple(String[] wifKeys) {
            ConversionResult result = new ConversionResult();

            for (String wif : wifKeys) {
                try {
                    String publicKey = wifTo34CharPublicKey(wif);
                    boolean isValidLength = is34CharPublicKey(publicKey);

                    result.addSuccess(wif, publicKey, isValidLength);
                } catch (Exception e) {
                    result.addFailure(wif, e.getMessage());
                }
            }

            return result;
        }
    }

    public static class ConversionResult {
        private int successCount = 0;
        private int failureCount = 0;
        private java.util.List<SuccessRecord> successes = new java.util.ArrayList<>();
        private java.util.List<FailureRecord> failures = new java.util.ArrayList<>();

        public void addSuccess(String wif, String publicKey, boolean isValidLength) {
            successes.add(new SuccessRecord(wif, publicKey, isValidLength));
            successCount++;
        }

        public void addFailure(String wif, String error) {
            failures.add(new FailureRecord(wif, error));
            failureCount++;
        }

        // Getters
        public int getSuccessCount() { return successCount; }
        public int getFailureCount() { return failureCount; }
        public java.util.List<SuccessRecord> getSuccesses() { return successes; }
        public java.util.List<FailureRecord> getFailures() { return failures; }
    }

    public static class SuccessRecord {
        private final String wif;
        private final String publicKey;
        private final boolean validLength;

        public SuccessRecord(String wif, String publicKey, boolean validLength) {
            this.wif = wif;
            this.publicKey = publicKey;
            this.validLength = validLength;
        }

        // Getters
        public String getWif() { return wif; }
        public String getPublicKey() { return publicKey; }
        public boolean isValidLength() { return validLength; }
    }

    public static class FailureRecord {
        private final String wif;
        private final String error;

        public FailureRecord(String wif, String error) {
            this.wif = wif;
            this.error = error;
        }

        // Getters
        public String getWif() { return wif; }
        public String getError() { return error; }
    }
}
